/**
 * MCU 适配层
 */
#include "xil_io.h"

#include "sysinc.h"
#include "mcu.h"

/// 应用层日志标签
#define LOGTAG "MCU"

uint32_t getU32(const void *stream) {
	uint8_t *buf = (uint8_t*)stream;
	return MAKE_DWORD(buf[0], buf[1], buf[2], buf[3]);
}

uint16_t getU16(const void *stream) {
	uint8_t *buf = (uint8_t*)stream;
	return MAKE_WORD(buf[0], buf[1]);
}

void osSystemReboot() {
	// SLCR寄存器，绝对地址
	#define REGADDR_SLCR_UNLOCK 	0xF8000008	// SLCR 解锁寄存器
	#define REGADDR_SLCR_LOCK   	0xF8000004	// SLCR 加锁寄存器
	#define UNLOCK_KEY          	0xDF0D		// 解锁码
	#define LOCK_KEY            	0x767B		// 加锁码
	// 参见 UG585 中 Register (slcr) PSS_RST_CTRL
	#define REGADDR_PSS_RST_CTRL	0xF8000200

	// 解锁
	Xil_Out32(REGADDR_SLCR_UNLOCK, UNLOCK_KEY);
	// asserts PS software reset pulse (entire system except clock generator).
	Xil_Out32(REGADDR_PSS_RST_CTRL, 0x00000001);
	// 加锁
	Xil_Out32(REGADDR_SLCR_LOCK, LOCK_KEY);
}

uint32_t osGetBootMode() {
	// 参见 UG585 中 Register (slcr) BOOT_MODE
	#define REGADDR_BOOT_MODE 0xF800025C
	uint32_t flag = Xil_In32(REGADDR_BOOT_MODE);
	uint32_t boot_mode  = flag & 0x0F;
	uint32_t pll_bypass = flag & 0x10;
	return boot_mode;
}

uint32_t osGetResetReason() {
	// 参见 UG585 中 Register (slcr) REBOOT_STATUS
	// 参见 UG585 中 Table 6‐2: Reboot Status Register
	// The Reboot Status register is reset by a POR reset, but preserved by a non-POR reset.
	#define REGADDR_REBOOT_STATUS 0xF8000258
	#define SUCCESSFUL_JTAG_SLAVE			0x0002 // The system successfully booted in JTAG mode.
	#define LQSPI_PERIPHERAL_INIT_ERROR		0x2000 // QSPI boot failed
	#define NAND_PERIPHERAL_INIT_ERROR		0x2001 // NAND boot failed
	#define SDC_PERIPHERAL_INIT_ERROR		0x200A // SD card boot failed
	#define NOR_PERIPHERAL_INIT_ERROR		0x200B // NOR boot failed
	#define LQSPI_MAX_OFFSET_GIS_HUNT_ERROR	0x200C // QSPI boot failed
	#define NAND_MAX_OFFSET_GIS_HUNT_ERROR	0x200D // SD card boot failed
	#define REGISTER INIT ERROR				0x200E

	uint32_t flag = Xil_In32(REGADDR_REBOOT_STATUS);
	if(flag == SUCCESSFUL_JTAG_SLAVE) {
	} else if(flag == SUCCESSFUL_JTAG_SLAVE) {
	}
	return flag;
}

int osIsAbnormalReboot() {
	return FALSE;
}

std_err_t osGetChipId(uint8_t id[12]) {
	return STD_ERR_OK;
}

std_err_t mcu_init() {
	return STD_ERR_OK;
}
